﻿#region Copyright (c) 2000-2008 Developer Express Inc.
/*
{*******************************************************************}
{                                                                   }
{       Developer Express .NET Component Library                    }
{       AgDataGrid                                 }
{                                                                   }
{       Copyright (c) 2000-2008 Developer Express Inc.              }
{       ALL RIGHTS RESERVED                                         }
{                                                                   }
{   The entire contents of this file is protected by U.S. and       }
{   International Copyright Laws. Unauthorized reproduction,        }
{   reverse-engineering, and distribution of all or any portion of  }
{   the code contained in this file is strictly prohibited and may  }
{   result in severe civil and criminal penalties and will be       }
{   prosecuted to the maximum extent possible under the law.        }
{                                                                   }
{   RESTRICTIONS                                                    }
{                                                                   }
{   THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES           }
{   ARE CONFIDENTIAL AND PROPRIETARY TRADE                          }
{   SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS   }
{   LICENSED TO DISTRIBUTE THE PRODUCT AND ALL ACCOMPANYING .NET    }
{   CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY.                 }
{                                                                   }
{   THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED      }
{   FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE        }
{   COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE       }
{   AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT  }
{   AND PERMISSION FROM DEVELOPER EXPRESS INC.                      }
{                                                                   }
{   CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON       }
{   ADDITIONAL RESTRICTIONS.                                        }
{                                                                   }
{*******************************************************************}
*/
#endregion Copyright (c) 2000-2008 Developer Express Inc.

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Threading;
using System.Collections;
using System.Windows.Data;
using System.Windows.Controls.Primitives;
using DevExpress.AgMenu.Utils;
using DevExpress.AgMenu.Internal;
namespace DevExpress.AgMenu {
	public enum AgMenuItemCheckAreaVisibility {
		None, ReplaceIcon, ShowCheckInSeparateArea, ShowEmptyCheckArea
	}
	public enum AgMenuItemState {
		Normal = 0,
		Hot = 1,
		Pressed = 2,
		Disabled = 3,
		DroppedDown = 4,
		Selected = 8
	}
	public enum AgMenuItemViewStyle {
		MenuItem,
		MenuSubItem,
		PopupMenuItem,
		PopupMenuSubItem
	}
	public delegate void AgMenuItemBeforePopupEventHandler(object sender, AgMenuItemBeforePopupEventArgs e);
	public class AgMenuItemBeforePopupEventArgs : EventArgs {
		public bool Cancel { get; set; }
		public AgMenuItemBeforePopupEventArgs() { Cancel = false; }
	}
	public delegate void AgMenuItemPopupAnimateEventHandler(object sender, AgMenuItemPopupAnimateEventArgs e);
	public class AgMenuItemPopupAnimateEventArgs : EventArgs {
		public bool IsShowing { get; private set; }
		public bool Handled { get; set; }
		public AgMenuItemPopupAnimateEventArgs(bool isShowing) {
			IsShowing = isShowing;
			Handled = true;
		}
	}
	public enum AgMenuItemPosition { First, Middle, Last, Single };
	public class AgMenuItemBase : ItemsControl, IAgMenuPanelChild {
		public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register("Header", typeof(object), typeof(AgMenuItemBase),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItemBase)d).HeaderChanged(e.OldValue);
		}));
		public static readonly DependencyProperty HeaderTemplateProperty = DependencyProperty.Register("HeaderTemplate", typeof(DataTemplate), typeof(AgMenuItemBase),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItemBase)d).HeaderTemplateChanged((DataTemplate)e.OldValue);
		}));
		public static readonly DependencyProperty IconProperty = DependencyProperty.Register("Icon", typeof(object), typeof(AgMenuItemBase),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItemBase)d).IconChanged(e.OldValue);
		}));
		const string ElementContentPresenterName = "ElementContentPresenter";
		const string ElementRootName = "ElementRoot";
		#region Fields
		UIElement contentPresenter;
		AgMenuBase menu;
		FrameworkElement rootElement;
		#endregion
		#region Properties
		public object Header {
			get { return this.GetValue(HeaderProperty); }
			set { SetValue(HeaderProperty, value); }
		}
		public DataTemplate HeaderTemplate {
			get { return (DataTemplate)GetValue(HeaderTemplateProperty); }
			set { SetValue(HeaderTemplateProperty, value); }
		}
		public object Icon {
			get { return this.GetValue(IconProperty); }
			set { SetValue(IconProperty, value); }
		}
		public virtual bool IsDroppedDown { get { return false; } set { } }
		public object Item { get; protected internal set; }
		public new virtual ItemCollection Items { get { return base.Items; } }
		public new virtual IEnumerable ItemsSource { get { return base.ItemsSource; } set { base.ItemsSource = value; } }
		public AgMenuBase Menu {
			get { return menu; }
			internal set {
				if (value == menu) return;
				menu = value;
				MenuChanged();
			}
		}
		public AgMenuItemBase ParentItem {
			get {
				return (Menu.IsRootMenu) ? null : (AgMenuItemBase)((AgPopupMenu)Menu).PopupElement;
			}
		}
		public virtual AgMenuItemState State {
			get {
				if (!IsEnabled)
					return AgMenuItemState.Disabled;
				else
					return (this == Menu.RootMenu.SelectedItem) ? AgMenuItemState.Selected : AgMenuItemState.Normal;
			}
		}
		public virtual AgPopupMenu SubMenu { get { return null; } }
		public virtual bool IsSubItem { get { return false; } }
		#endregion
		#region Methods
		public AgMenuItemBase() {
			DefaultStyleKey = typeof(AgMenuItemBase);
			IsEnabledChanged += OnIsEnabledChanged;
			LayoutUpdated += OnLayoutUpdated;
			Loaded += OnLoaded;
		}
		public virtual bool CanFocus() { return false; }
		public override void OnApplyTemplate() {
			base.OnApplyTemplate();
			contentPresenter = GetTemplateChild(ElementContentPresenterName) as UIElement;
			rootElement = GetTemplateChild(ElementRootName) as FrameworkElement;
		}
		protected internal virtual bool DoAnimateSubMenu(bool isShowing) {
			return false;
		}
		protected internal virtual void AssignTemplate(DataTemplate template) {
			if (template is AgMenuSubItemDataTemplate) {
				AgMenuSubItemDataTemplate template1 = (template as AgMenuSubItemDataTemplate);
				if (template1.ItemsSource != null)
					SetBinding(ItemsSourceProperty, template1.ItemsSource);
				ItemTemplate = template1.ItemTemplate;
				if (template1.HeaderTemplate != null)
					HeaderTemplate = template1.HeaderTemplate;
			} else
				HeaderTemplate = template;
		}
		protected internal virtual void OnSubMenuClosed() { }
		protected internal virtual void OnSubMenuOpened() { }
		protected internal virtual void PrepareForTemplateChanging() {
			if (Header is FrameworkElement)
				(Header as FrameworkElement).ClearParent();
			if (Icon is FrameworkElement)
				(Icon as FrameworkElement).ClearParent();
		}
		protected internal virtual void StateChanged() {
			UpdateAppearance();
			AgMenuItemBase droppedDownItem = Menu.GetDroppedDownItem();
			if (droppedDownItem != null && droppedDownItem != this)
				droppedDownItem.UpdateAppearance();
		}
		protected virtual void HeaderChanged(object oldValue) { }
		protected virtual void HeaderTemplateChanged(DataTemplate oldValue) { }
		protected virtual void IconChanged(object oldValue) { }
		protected virtual void MenuChanged() {
			UpdateMenuOrientation();
			UpdateViewStyle();
		}
		protected void MenuCheckItemState(AgMenuItemState oldState) {
			AgMenuBase.CheckItemState(this, oldState);
		}
		protected Orientation MenuGetOrientation() {
			return Menu.GetOrientation();
		}
		protected bool MenuHasEmptyArea() {
			return Menu.HasEmptyArea();
		}
		protected void MenuItemStateChanged() {
			Menu.ItemStateChanged(this);
		}
		protected void MenuUpdateItemTemplate() {
			if (Menu == null) return;
			Menu.UpdateItemTemplate(this);
		}
		protected virtual void OnIsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e) {
			if (Menu != null)
				MenuItemStateChanged();
		}
		protected virtual void OnLayoutUpdated(object sender, EventArgs e) {
			if (Menu != null) {
				UpdateMenuOrientation();
				UpdateViewStyle();
				UpdatePosition();
				MenuUpdateItemTemplate();
			}
		}
		protected virtual void OnLoaded(object sender, RoutedEventArgs e) {
			UpdateAppearance();
			if (Menu.IsPopupMenu) return;
			IEnumerable items = (ItemsSource != null) ? ItemsSource : Items;
			foreach (object item in items)
				if (item is AgMenuItemBase) {
					AgMenuItemBase menuItem = item as AgMenuItemBase;
					if (menuItem.Template != null) continue;
					menuItem.Template = Menu.GetItemContainerTemplate(menuItem.GetType(), Orientation.Vertical, AgMenuItemPosition.First,
						menuItem.IsSubItem ? AgMenuItemViewStyle.PopupMenuSubItem : AgMenuItemViewStyle.PopupMenuItem);
					menuItem.ApplyTemplate();
				}
		}
		protected virtual void Select() {
			AgMenuBase rootMenu = Menu.RootMenu;
			if (rootMenu.AllowSelectItems)
				rootMenu.SelectedItem = this;
		}
		protected internal virtual bool HandleKeyDown(Key key) {
			return false;
		}
		#endregion
		#region Interfaces
		double IAgMenuPanelChild.IconAreaLeft {
			get {
				if (this.contentPresenter is IAgMenuItemContentPresenter) {
					return (this.contentPresenter as IAgMenuItemContentPresenter).IconAreaLeft +
						((FrameworkElement)this.contentPresenter).GetPositionNew(this).X;
				}
				return 0;
			}
		}
		double IAgMenuPanelChild.IconAreaWidth {
			get {
				return (this.contentPresenter is IAgMenuItemContentPresenter) ? (this.contentPresenter as IAgMenuItemContentPresenter).IconAreaWidth : 0;
			}
			set {
				if (this.contentPresenter is IAgMenuItemContentPresenter)
					(this.contentPresenter as IAgMenuItemContentPresenter).IconAreaWidth = value;
			}
		}
		bool IAgMenuPanelChild.IsFirstVisibleChild { set { IsFirstVisibleItem = value; } }
		bool IAgMenuPanelChild.IsLastVisibleChild { set { IsLastVisibleItem = value; } }
		Size IAgMenuPanelChild.DesiredSize {
			get { return new Size(Math.Ceiling(DesiredSize.Width), Math.Ceiling(DesiredSize.Height)); }
		}
		VerticalAlignment IAgMenuPanelChild.VerticalAlignment {
			get { return GetVerticalAlignment(); }
		}
		void IAgMenuPanelChild.PrepareForVerticalLayout(List<IAgMenuPanelChild> items) {
			foreach (IAgMenuPanelChild item in items)
				Debug.Assert(item is AgMenuItemBase);
			List<IAgMenuItemContentPresenter> list = new List<IAgMenuItemContentPresenter>();
			foreach (AgMenuItemBase item in items)
				if (item.contentPresenter is IAgMenuItemContentPresenter)
					list.Add(item.contentPresenter as IAgMenuItemContentPresenter);
			if (list.Count > 0)
				list[0].PrepareForVerticalLayout(list);
		}
		protected virtual VerticalAlignment GetVerticalAlignment() {
			return VerticalAlignment;
		}
		#endregion
		#region Appearance
		protected enum MenuItemVisualState {
			Normal, Hot, Pressed, DroppedDown, DroppedDownSelected, DroppedDownHot, DroppedDownPressed, Disabled, Selected
		}
		bool isFirstVisibleItem;
		bool isLastVisibleItem;
		public static readonly DependencyProperty MenuOrientationProperty = DependencyProperty.Register("MenuOrientation", typeof(Orientation), typeof(AgMenuItemBase),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItemBase)d).MenuOrientationChanged();
		}));
		public static readonly DependencyProperty ViewStyleProperty = DependencyProperty.Register("ViewStyle", typeof(AgMenuItemViewStyle), typeof(AgMenuItemBase),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItemBase)d).ViewStyleChanged((AgMenuItemViewStyle)e.OldValue);
		}));
		public static readonly DependencyProperty PositionProperty = DependencyProperty.Register("Position", typeof(AgMenuItemPosition), typeof(AgMenuItemBase),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItemBase)d).PositionChanged();
		}));
		public Orientation MenuOrientation {
			get { return (Orientation)GetValue(MenuOrientationProperty); }
		}
		public AgMenuItemViewStyle ViewStyle {
			get { return (AgMenuItemViewStyle)GetValue(ViewStyleProperty); }
		}
		public AgMenuItemPosition Position { get { return (AgMenuItemPosition)GetValue(PositionProperty); } }
		protected virtual MenuItemVisualState VisualState {
			get {
				if (!IsEnabled)
					return MenuItemVisualState.Disabled;
				else
					return (this == Menu.RootMenu.SelectedItem) ? MenuItemVisualState.Selected : MenuItemVisualState.Normal;
			}
		}
		bool IsFirstVisibleItem {
			get { return isFirstVisibleItem; }
			set {
				if (value == isFirstVisibleItem) return;
				isFirstVisibleItem = value;
				UpdatePosition();
			}
		}
		bool IsLastVisibleItem {
			get { return isLastVisibleItem; }
			set {
				if (value == isLastVisibleItem) return;
				isLastVisibleItem = value;
				UpdatePosition();
			}
		}
		protected void GoToState(string[] stateNames, bool useTransitions) {
			foreach (string stateName in stateNames) {
				if (VisualStateManager.GoToState(this, stateName, useTransitions)) {
					return;
				}
			}
		}
		protected virtual void MenuOrientationChanged() { }
		protected virtual void ViewStyleChanged(AgMenuItemViewStyle oldValue) { }
		protected virtual void PositionChanged() { }
		protected virtual void UpdateAppearance() {
			GoToState(GetVisualStateNames(VisualState), true);
		}
		protected virtual string[] GetVisualStateNames(MenuItemVisualState state) {
			switch (state) {
				case MenuItemVisualState.Normal:
					return new string[] { "Normal" };
				case MenuItemVisualState.Hot:
					return new string[] { "Hot", "Normal" };
				case MenuItemVisualState.Pressed:
					return new string[] { "Pressed", "Hot", "Normal" };
				case MenuItemVisualState.DroppedDown:
					return new string[] { "DroppedDown", "DroppedDownSelected", "Normal" };
				case MenuItemVisualState.DroppedDownSelected:
					return new string[] { "DroppedDownSelected", "Normal" };
				case MenuItemVisualState.DroppedDownHot:
					return new string[] { "DroppedDownHot", "DroppedDownSelected", "Normal" };
				case MenuItemVisualState.DroppedDownPressed:
					return new string[] { "DroppedDownPressed", "DroppedDownHot", "DroppedDownSelected", "Normal" };
				case MenuItemVisualState.Disabled:
					return new string[] { "Disabled", "Normal" };
				case MenuItemVisualState.Selected:
					return new string[] { "Selected", "Normal" };
				default:
					throw new Exception();
			}
		}
		void UpdateMenuOrientation() {
			if (Menu == null) return;
			SetValue(MenuOrientationProperty, MenuGetOrientation());
		}
		void UpdatePosition() {
			if (Menu == null) return;
			bool menuHasEmptyArea = MenuHasEmptyArea();
			if (IsFirstVisibleItem) {
				if (isLastVisibleItem && !menuHasEmptyArea)
					SetValue(PositionProperty, AgMenuItemPosition.Single);
				else
					SetValue(PositionProperty, AgMenuItemPosition.First);
			} else
				if (isLastVisibleItem && !menuHasEmptyArea)
					SetValue(PositionProperty, AgMenuItemPosition.Last);
				else
					SetValue(PositionProperty, AgMenuItemPosition.Middle);
		}
		void UpdateViewStyle() {
			if (Menu == null) return;
			if (!Menu.IsPopupMenu)
				SetValue(ViewStyleProperty, !IsSubItem ? AgMenuItemViewStyle.MenuItem : AgMenuItemViewStyle.MenuSubItem);
			else
				SetValue(ViewStyleProperty, !IsSubItem ? AgMenuItemViewStyle.PopupMenuItem : AgMenuItemViewStyle.PopupMenuSubItem);
		}
		#endregion
	}
	public class AgMenuItem : AgMenuItemBase {
		const string ElementPopupName = "ElementPopup";
		public static readonly DependencyProperty CheckAreaVisibilityProperty = DependencyProperty.Register("CheckAreaVisibility", typeof(AgMenuItemCheckAreaVisibility), typeof(AgMenuItem),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItem)d).CheckAreaVisibilityChanged();
		}));
		public static readonly DependencyProperty ClosePopupOnClickProperty = DependencyProperty.Register("ClosePopupOnClick", typeof(bool), typeof(AgMenuItem),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItem)d).ClosePopupOnClickChanged();
		}));
		public static readonly DependencyProperty GroupProperty = DependencyProperty.Register("Group", typeof(object), typeof(AgMenuItem),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItem)d).GroupChanged(e.OldValue);
		}));
		public static readonly DependencyProperty IsCheckableProperty = DependencyProperty.Register("IsCheckable", typeof(bool), typeof(AgMenuItem),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItem)d).IsCheckableChanged();
		}));
		public static readonly DependencyProperty IsCheckedProperty = DependencyProperty.Register("IsChecked", typeof(bool), typeof(AgMenuItem),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItem)d).IsCheckedChanged();
		}));
		public static readonly DependencyProperty IsRadioItemProperty = DependencyProperty.Register("IsRadioItem", typeof(bool), typeof(AgMenuItem),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItem)d).IsRadioItemChanged();
		}));
		public static readonly DependencyProperty SubMenuStyleProperty = DependencyProperty.Register("SubMenuStyle", typeof(Style), typeof(AgMenuItem),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItem)d).SubMenuStyleChanged((Style)e.OldValue);
		}));
		public static readonly DependencyProperty SubMenuStyleSelectorProperty = DependencyProperty.Register("SubMenuStyleSelector", typeof(AgMenuSubMenuStyleSelector),
			typeof(AgMenuItem), new PropertyMetadata((d, e) => ((AgMenuItem)d).PropertyChangedSubMenuStyleSelector()));
		bool isLoaded;
		AgPopupMenu openSubMenu;
		AgPopupMenu subMenu;
		public AgMenuItemCheckAreaVisibility CheckAreaVisibility {
			get { return (AgMenuItemCheckAreaVisibility)GetValue(CheckAreaVisibilityProperty); }
		}
		public override bool IsDroppedDown {
			get { return SubMenu != null; }
			set {
				if (IsDroppedDown != value)
					if (value)
						Popup();
					else
						CloseUp();
			}
		}
		public object Group {
			get { return this.GetValue(GroupProperty); }
			set { base.SetValue(GroupProperty, value); }
		}
		public bool IsCheckable {
			get { return (bool)this.GetValue(IsCheckableProperty); }
			set { base.SetValue(IsCheckableProperty, value); }
		}
		public bool IsChecked {
			get { return (bool)this.GetValue(IsCheckedProperty); }
			set { base.SetValue(IsCheckedProperty, value); }
		}
		public bool IsRadioItem {
			get { return (bool)this.GetValue(IsRadioItemProperty); }
			set { base.SetValue(IsRadioItemProperty, value); }
		}
		public override bool IsSubItem { get { return Items.Count != 0 || ItemsSource != null; } }
		public override ItemCollection Items {
			get { return (openSubMenu != null) ? openSubMenu.Items : base.Items; }
		}
		public override IEnumerable ItemsSource {
			get { return (openSubMenu != null) ? openSubMenu.ItemsSource : base.ItemsSource; }
			set {
				if (openSubMenu != null)
					openSubMenu.ItemsSource = value;
				else
					base.ItemsSource = value;
			}
		}
		public override AgPopupMenu SubMenu { get { return subMenu; } }
		public Style SubMenuStyle {
			get { return (Style)GetValue(SubMenuStyleProperty); }
			set { SetValue(SubMenuStyleProperty, value); }
		}
		public AgMenuSubMenuStyleSelector SubMenuStyleSelector {
			get { return (AgMenuSubMenuStyleSelector)GetValue(SubMenuStyleSelectorProperty); }
			set { SetValue(SubMenuStyleSelectorProperty, value); }
		}
		protected Popup ElementPopup { get; private set; }
		protected bool IsTargetForClosingUp {
			get { return CloseUpController.IsTargetForClosingUp(this); }
		}
		protected bool MenuHasCheckedItems { get { return Menu.HasCheckedItems; } }
		protected override MenuItemVisualState VisualState {
			get {
				MenuItemVisualState result;
				if (!IsEnabled)
					result = MenuItemVisualState.Disabled;
				else
					if (this == Menu.RootMenu.SelectedItem)
						result = MenuItemVisualState.Selected;
					else
						if (!IsDroppedDown) {
							if (CloseUpController.HighlightedItem != this)
								result = MenuItemVisualState.Normal;
							else
								result = Pressed ? MenuItemVisualState.Pressed : MenuItemVisualState.Hot;
						} else {
							if (CloseUpController.HighlightedItem != this) {
								bool closeUpSubItemIfNotSelected = !(Menu.RootMenu.IsPopupMenu || Menu.RootMenu.OpenSubMenuOnClick);
								bool needsDrawSelection = !closeUpSubItemIfNotSelected && IsDroppedDown && !IsTargetForClosingUp ||
									closeUpSubItemIfNotSelected && IsDroppedDown && (CloseUpController.HighlightedItem == null || CloseUpController.HighlightedItem.Menu != Menu);
								result = needsDrawSelection ? MenuItemVisualState.DroppedDownSelected : MenuItemVisualState.DroppedDown;
							} else
								result = Pressed ? MenuItemVisualState.DroppedDownPressed : MenuItemVisualState.DroppedDownHot;
						}
				return result;
			}
		}
		public event AgMenuItemBeforePopupEventHandler BeforePopup;
		public event EventHandler Checked;
		public event AgMenuItemPopupAnimateEventHandler PopupAnimate;
		public event EventHandler SubMenuClosed;
		public event EventHandler SubMenuOpened;
		public event EventHandler Unchecked;
		public AgMenuItem() {
			ClosePopupOnClick = true;
			MouseEnter += OnMouseEnter;
			MouseLeave += OnMouseLeave;
			MouseLeftButtonDown += OnMouseLeftButtonDown;
			MouseLeftButtonUp += OnMouseLeftButtonUp;
			MouseMove += OnMouseMove;
		}
		public override void OnApplyTemplate() {
			base.OnApplyTemplate();
			ElementPopup = GetTemplateChild(ElementPopupName) as Popup;
		}
		protected internal override bool DoAnimateSubMenu(bool isShowing) {
			if(!RaisePopupAnimate(isShowing) && !MenuAnimateItemSubMenu(isShowing))
				return base.DoAnimateSubMenu(isShowing);
			else
				return true;
		}
		protected internal override void OnSubMenuClosed() {
			base.OnSubMenuClosed();
			CheckPopupTimerTarget(openSubMenu);
			ClearSubMenu(openSubMenu);
			this.subMenu = openSubMenu;
			openSubMenu = null;
			try {
				DoSubMenuClosed();
			} finally {
				this.subMenu = null;
			}
		}
		protected internal override void OnSubMenuOpened() {
			base.OnSubMenuOpened();
			DoSubMenuOpened();
		}
		protected internal void UpdateCheckAreaVisibility() {
			if (Menu != null)
				switch (Menu.RootMenu.CheckAreaDisplayMode) {
					case AgMenuCheckAreaDisplayMode.AlwaysShowCheckArea:
						SetValue(CheckAreaVisibilityProperty, IsChecked ? AgMenuItemCheckAreaVisibility.ShowCheckInSeparateArea : AgMenuItemCheckAreaVisibility.ShowEmptyCheckArea);
						break;
					case AgMenuCheckAreaDisplayMode.ReplaceIcon:
						SetValue(CheckAreaVisibilityProperty, IsChecked ? AgMenuItemCheckAreaVisibility.ReplaceIcon : AgMenuItemCheckAreaVisibility.None);
						break;
					case AgMenuCheckAreaDisplayMode.ShowCheckAreaIfChecked:
						if (IsChecked)
							SetValue(CheckAreaVisibilityProperty, AgMenuItemCheckAreaVisibility.ShowCheckInSeparateArea);
						else
							SetValue(CheckAreaVisibilityProperty, MenuHasCheckedItems ? AgMenuItemCheckAreaVisibility.ShowEmptyCheckArea : AgMenuItemCheckAreaVisibility.None);
						break;
				}
		}
		public override bool CanFocus() { return this.GetVisible() && IsEnabled; }
		protected virtual void CheckAreaVisibilityChanged() { }
		protected void CloseUp() {
			StopPopupTimer(this);
			subMenu.CloseUp();
			SetSubMenu(null);
		}
		protected virtual bool DoBeforePopup() {
			return RaiseBeforePopup() && MenuDoItemBeforePopup();
		}
		protected virtual void DoChecked() {
			RaiseChecked();
			MenuDoItemChecked();
		}
		protected virtual void DoSubMenuClosed() {
			MenuDoItemSubMenuClosed();
			RaiseSubMenuClosed();
		}
		protected virtual void DoSubMenuOpened() {
			MenuDoItemSubMenuOpened();
			RaiseSubMenuOpened();
		}
		protected virtual void DoUnchecked() {
			RaiseUnchecked();
			MenuDoItemUnchecked();
		}
		protected virtual Point GetAbsolutePosition() {
			if (Menu.RootMenu.IsPopupMenu)
				return this.GetPositionNew(null);
			AgMenuItem item = this;
			do {
				if (item.ElementPopup == null)
					return this.GetPositionNew(null);
				item = item.ParentItem as AgMenuItem;
			} while (item != null);
			return this.GetPosition(null);
		}
		protected virtual void GroupChanged(object oldValue) { }
		protected virtual Rect SubMenuOwnerBounds {
			get {
				Point p = GetAbsolutePosition();
				Size size = this.GetSize();
				return new Rect(p.X, p.Y, size.Width, size.Height);
			}
		}
		protected virtual void InitSubMenu() {
			subMenu.PopupAlign = (MenuOrientation == Orientation.Horizontal) ? Orientation.Vertical : Orientation.Horizontal;
			subMenu.PopupElement = this;
			subMenu.PopupElementRect = SubMenuOwnerBounds;
			Style subMenuStyle = GetSubMenuStyle(subMenu);
			if (subMenuStyle != null)
				subMenu.Style = subMenuStyle;
			this.MoveItemsTo(subMenu);
			subMenu.ItemTemplate = ItemTemplate;
			subMenu.Container = ElementPopup;
			if (ElementPopup != null) {
				Point p = GetAbsolutePosition();
				ElementPopup.Margin = new Thickness(-p.X, -p.Y, 0, 0);
			}
		}
		void ClearSubMenu(AgPopupMenu subMenu) {
			subMenu.MoveItemsTo(this);
		}
		protected virtual void IsCheckableChanged() { }
		protected virtual void IsCheckedChanged() {
			if (Menu != null)
				MenuItemIsCheckedChanged();
			if (isLoaded)
				if (IsChecked)
					DoChecked();
				else
					DoUnchecked();
			UpdateCheckAreaVisibility();
		}
		protected virtual void IsRadioItemChanged() { }
		protected bool MenuAnimateItemSubMenu(bool isShowing) {
			return Menu.RootMenu.AnimateItemSubMenu(this, isShowing);
		}
		protected bool MenuDoItemBeforePopup() {
			return Menu.RootMenu.DoItemBeforePopup(this);
		}
		protected void MenuDoItemChecked() {
			if (Menu != null)
				Menu.RootMenu.DoItemChecked(this);
		}
		protected void MenuDoItemSubMenuClosed() {
			if (Menu != null)
				Menu.RootMenu.DoItemSubMenuClosed(this);
		}
		protected void MenuDoItemSubMenuOpened() {
			if (Menu != null)
				Menu.RootMenu.DoItemSubMenuOpened(this);
		}
		protected void MenuDoItemUnchecked() {
			if (Menu != null)
				Menu.RootMenu.DoItemUnchecked(this);
		}
		protected void MenuItemIsCheckedChanged() {
			if (Menu != null)
				Menu.ItemIsCheckedChanged(this);
		}
		protected override void OnLayoutUpdated(object sender, EventArgs e) {
			base.OnLayoutUpdated(sender, e);
			UpdateCheckAreaVisibility();
		}
		protected override void OnLoaded(object sender, RoutedEventArgs e) {
			base.OnLoaded(sender, e);
			isLoaded = true;
		}
		protected static void PopupMenuForcedCloseUp(AgPopupMenu subMenu) {
			subMenu.ForcedCloseUp();
		}
		protected virtual bool RaisePopupAnimate(bool isShowing) {
			if(PopupAnimate != null) {
				AgMenuItemPopupAnimateEventArgs e = new AgMenuItemPopupAnimateEventArgs(isShowing);
				PopupAnimate(this, e);
				return !e.Handled;
			} else
				return false;
		}
		protected virtual void RaiseSubMenuClosed() {
			if (SubMenuClosed != null)
				SubMenuClosed(this, new EventArgs());
		}
		protected virtual void RaiseSubMenuOpened() {
			if (SubMenuOpened != null)
				SubMenuOpened(this, new EventArgs());
		}
		protected void Popup() {
			if (IsDroppedDown || !DoBeforePopup() || !IsSubItem) return;
			Menu.CloseSubMenus(); 
			if (openSubMenu != null) {
				PopupMenuForcedCloseUp(openSubMenu);
			}
			SetSubMenu(CreateSubMenu());
			openSubMenu = SubMenu;
			InitSubMenu();
			subMenu.Popup();
		}
		protected virtual void PropertyChangedSubMenuStyleSelector() { }
		protected virtual bool RaiseBeforePopup() {
			if (BeforePopup == null)
				return true;
			else {
				AgMenuItemBeforePopupEventArgs e = new AgMenuItemBeforePopupEventArgs();
				BeforePopup(this, e);
				return !e.Cancel;
			}
		}
		protected virtual void RaiseChecked() {
			if (Checked != null)
				Checked(this, new EventArgs());
		}
		protected virtual void RaiseUnchecked() {
			if (Unchecked != null)
				Unchecked(this, new EventArgs());
		}
		protected virtual AgPopupMenu CreateSubMenu() {
			return new AgPopupMenu();
		}
		protected void SetSubMenu(AgPopupMenu value) {
			AgMenuItemState oldState = State;
			subMenu = value;
			MenuCheckItemState(oldState);
		}
		protected virtual void SubMenuStyleChanged(Style oldValue) { }
		internal Style GetSubMenuStyle(AgPopupMenu subMenu) {
			if (SubMenuStyle != null || SubMenuStyleSelector != null)
				return SubMenuStyle ?? SubMenuStyleSelector.SelectStyle(subMenu);
			else {
				AgMenuBase menu = Menu;
				if (menu.IsRootMenu) {
					Style result = menu.SubMenuStyle;
					if (result == null && menu.SubMenuStyleSelector != null)
						result = menu.SubMenuStyleSelector.SelectStyle(subMenu);
					return result;
				}
				else
					return ((AgMenuItem)((AgPopupMenu)menu).PopupElement).GetSubMenuStyle(subMenu);
			}
		}
		#region Mouse behavior
		static DispatcherTimer popupTimer;
		static AgMenuItemBase popupTimerTarget;
		bool pressed;
		bool pressedForItemSelection;
		public bool ClosePopupOnClick {
			get { return (bool)GetValue(ClosePopupOnClickProperty); }
			set { SetValue(ClosePopupOnClickProperty, value); }
		}
		public override AgMenuItemState State {
			get {
				AgMenuItemState result;
				if (!IsEnabled || CloseUpController.HighlightedItem != this)
					result = !IsEnabled ? AgMenuItemState.Disabled : AgMenuItemState.Normal;
				else
					result = Pressed ? AgMenuItemState.Pressed : AgMenuItemState.Hot;
				if (IsDroppedDown)
					result |= AgMenuItemState.DroppedDown;
				if (this == Menu.RootMenu.SelectedItem)
					result |= AgMenuItemState.Selected;
				return result;
			}
		}
		bool Pressed {
			get { return this.pressed; }
			set {
				if (value == this.pressed || value && IsSubItem) return;
				AgMenuItemState oldState = State;
				this.pressed = value;
				MenuCheckItemState(oldState);
			}
		}
		public event EventHandler Click;
		protected internal override bool HandleKeyDown(Key key) {
			if (key == Key.Enter) {
				if (IsSubItem) {
					IsDroppedDown = true;
					CloseUpController.SetHighlightedItem(SubMenu.GetNextItem(-1));
				} else {
					PerformClick();
					CloseUpController.SetHighlightedItem(null);
				}
				return true;
			}
			return false;
		}
		protected internal virtual void PerformClick() {
			HandleClick();
			DoClick();
			if (ClosePopupOnClick && Menu != null)
				Menu.CloseAllSubMenus();
		}
		protected virtual void ClosePopupOnClickChanged() { }
		protected virtual void DoClick() {
			MenuDoItemClick();
			RaiseClick();
		}
		protected virtual void HandleClick() {
			if (IsCheckable)
				if (IsRadioItem)
					IsChecked = true;
				else
					IsChecked = !IsChecked;
			Select();
		}
		protected void MenuDoItemClick() {
			Menu.RootMenu.DoItemClick(this);
		}
		protected static void MenuSetHighlightedItem(AgMenuItemBase value) { CloseUpController.SetHighlightedItem(value); }
		protected virtual void OnMouseEnter(object sender, MouseEventArgs e) {
			if (!IsEnabled) return;
			MenuSetHighlightedItem(this);
			if (IsDroppedDown) return;
			if (Menu.IsPopupMenu || !Menu.OpenSubMenuOnClick)
				StartPopupTimer(this);
			else
				if (Menu.AutoOpenSubMenusMode) {
					Menu.CloseSubMenus();
					IsDroppedDown = true;
				}
		}
		protected virtual void OnMouseLeave(object sender, EventArgs e) {
			if (!IsEnabled) return;
			Pressed = false;
			pressedForItemSelection = false;
			if (this == CloseUpController.HighlightedItem)
				MenuSetHighlightedItem(null);
			StopPopupTimer(this);
		}
		protected virtual void OnMouseLeftButtonDown(object sender, MouseEventArgs e) {
			if (!IsEnabled) return;
			Pressed = true;
			pressedForItemSelection = true;
			if (Menu.IsPopupMenu || !Menu.OpenSubMenuOnClick) return;
			if (IsDroppedDown)
				Menu.CloseAllSubMenus();
			else {
				IsDroppedDown = true;
				if (IsDroppedDown)
					Menu.AutoOpenSubMenusMode = true;
			}
		}
		protected virtual void OnMouseLeftButtonUp(object sender, MouseEventArgs e) {
			if (!IsEnabled) return;
			bool oldPressed = Pressed;
			bool oldPressedForItemSelection = pressedForItemSelection;
			Pressed = false;
			pressedForItemSelection = false;
			if (oldPressed)
				PerformClick();
			else
				if (oldPressedForItemSelection)
					Select();
		}
		protected virtual void OnMouseMove(object sender, MouseEventArgs e) {
			if (!IsEnabled) return;
			MenuSetHighlightedItem(this);
		}
		protected virtual void RaiseClick() {
			if (Click != null)
				Click(this, new EventArgs());
		}
		static void CheckPopupTimerTarget(AgPopupMenu closedPopupMenu) {
			if (popupTimerTarget != null && popupTimerTarget.Menu == closedPopupMenu)
				StopPopupTimer(popupTimerTarget);
		}
		static void OnPopupTimerTick(object sender, EventArgs e) {
			AgMenuItemBase oldPopupTimerTarget = popupTimerTarget;
			StopPopupTimer(popupTimerTarget);
			if (oldPopupTimerTarget != null)
				oldPopupTimerTarget.IsDroppedDown = true;
		}
		static void StartPopupTimer(AgMenuItemBase target) {
			if (target == null) throw new Exception("Target == null in StartPopupTimer");
			if (target == popupTimerTarget) return;
			if (popupTimerTarget != null)
				StopPopupTimer(popupTimerTarget);
			if (target.Menu.PopupDelay == TimeSpan.Zero) {
				OnPopupTimerTick(null, null);
				return;
			}
			popupTimerTarget = target;
			popupTimer = new DispatcherTimer();
			popupTimer.Interval = target.Menu.PopupDelay;
			popupTimer.Tick += OnPopupTimerTick;
			popupTimer.Start();
		}
		static void StopPopupTimer(AgMenuItemBase target) {
			if (target == null) {
				if (popupTimer != null) throw new Exception("Target == null in StopPopupTimer");
				return;
			}
			if (target != popupTimerTarget) return;
			popupTimerTarget = null;
			popupTimer.Stop();
			popupTimer = null;
		}
		#endregion
	}
	public class AgMenuSubItemDataTemplate : DataTemplate {
		public DataTemplate HeaderTemplate { get; set; }
		public Binding ItemsSource { get; set; }
		public DataTemplate ItemTemplate { get; set; }
	}
}
namespace DevExpress.AgMenu.Internal {
	public interface IAgMenuItemContentPresenter {
		double IconAreaLeft { get; }
		double IconAreaWidth { get; set; }
		void PrepareForVerticalLayout(List<IAgMenuItemContentPresenter> items);
	}
	public class AgMenuItemContentPresenter : System.Windows.Controls.Control, IAgMenuItemContentPresenter {
		protected override Size MeasureOverride(Size availableSize) {
			return base.MeasureOverride(availableSize);
		}
		public static readonly DependencyProperty CheckAreaVisibilityProperty = DependencyProperty.Register("CheckAreaVisibility", typeof(AgMenuItemCheckAreaVisibility), typeof(AgMenuItemContentPresenter),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItemContentPresenter)d).CheckAreaVisibilityChanged();
		}));
		public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(object), typeof(AgMenuItemContentPresenter),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItemContentPresenter)d).ContentChanged(e.OldValue);
		}));
		public static readonly DependencyProperty ContentTemplateProperty = DependencyProperty.Register("ContentTemplate", typeof(DataTemplate), typeof(AgMenuItemContentPresenter),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItemContentPresenter)d).ContentTemplateChanged((DataTemplate)e.OldValue);
		}));
		public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register("Header", typeof(object), typeof(AgMenuItemContentPresenter),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItemContentPresenter)d).HeaderChanged(e.OldValue);
		}));
		public static readonly DependencyProperty HeaderTemplateProperty = DependencyProperty.Register("HeaderTemplate", typeof(DataTemplate), typeof(AgMenuItemContentPresenter),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItemContentPresenter)d).HeaderTemplateChanged((DataTemplate)e.OldValue);
		}));
		public static readonly DependencyProperty IconProperty = DependencyProperty.Register("Icon", typeof(object), typeof(AgMenuItemContentPresenter),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItemContentPresenter)d).IconChanged(e.OldValue);
		}));
		public static readonly DependencyProperty IsRadioItemProperty = DependencyProperty.Register("IsRadioItem", typeof(bool), typeof(AgMenuItemContentPresenter),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItemContentPresenter)d).IsRadioItemChanged();
		}));
		public static readonly DependencyProperty MenuOrientationProperty = DependencyProperty.Register("MenuOrientation", typeof(Orientation), typeof(AgMenuItemContentPresenter),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItemContentPresenter)d).MenuOrientationChanged();
		}));
		public static readonly DependencyProperty TemplateCollectionProperty = DependencyProperty.Register("TemplateCollection", typeof(AgMenuTemplateList), typeof(AgMenuItemContentPresenter),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItemContentPresenter)d).TemplateCollectionChanged((AgMenuTemplateList)e.OldValue);
		}));
		public static readonly DependencyProperty ViewStyleProperty = DependencyProperty.Register("ViewStyle", typeof(AgMenuItemViewStyle), typeof(AgMenuItemContentPresenter),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItemContentPresenter)d).ViewStyleChanged((AgMenuItemViewStyle)e.OldValue);
		}));
		public static readonly DependencyProperty PositionProperty = DependencyProperty.Register("Position", typeof(AgMenuItemPosition), typeof(AgMenuItemContentPresenter),
			new PropertyMetadata(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((AgMenuItemContentPresenter)d).PositionChanged();
		}));
		enum IconCheckAreaAreaKind { Icon, Check }
		const string ElementCheckName = "ElementCheck";
		const string ElementCheckAreaName = "ElementCheckArea";
		const string ElementCheckAreaContainerName = "ElementCheckAreaContainer";
		const string ElementIconName = "ElementIcon";
		const string ElementIconAreaName = "ElementIconArea";
		const string ElementIconAreaContainerName = "ElementIconAreaContainer";
		const string ElementIconCheckAreaName = "ElementIconCheckArea";
		const string ElementIconCheckAreaContainerName = "ElementIconCheckAreaContainer";
		const string ElementRadioName = "ElementRadio";
		const string ElementContentName = "ElementContent";
		const string ElementRootName = "ElementRoot";
		static readonly string[] TemplateKeyNames = new string[] {
			"TemplateMenuItemContentPresenter",
			"TemplateMenuSubItemContentPresenter",
			"TemplatePopupMenuItemContentPresenter",
			"TemplatePopupMenuSubItemContentPresenter"
		};
		UIElement elementCheck;
		UIElement elementCheckArea;
		FrameworkElement elementCheckAreaContainer;
		UIElement elementIcon;
		UIElement elementIconArea;
		FrameworkElement elementIconAreaContainer;
		UIElement elementIconCheckArea;
		FrameworkElement elementIconCheckAreaContainer;
		UIElement elementRadio;
		UIElement elementContent;
		System.Windows.Controls.Panel elementRoot;
		public AgMenuItemCheckAreaVisibility CheckAreaVisibility {
			get { return (AgMenuItemCheckAreaVisibility)this.GetValue(CheckAreaVisibilityProperty); }
			set { base.SetValue(CheckAreaVisibilityProperty, value); }
		}
		public object Content {
			get { return GetValue(ContentProperty); }
			set { SetValue(ContentProperty, value); }
		}
		public DataTemplate ContentTemplate {
			get { return (DataTemplate)GetValue(ContentTemplateProperty); }
			set { SetValue(ContentTemplateProperty, value); }
		}
		public object Header {
			get { return GetValue(HeaderProperty); }
			set { SetValue(HeaderProperty, value); }
		}
		public DataTemplate HeaderTemplate {
			get { return (DataTemplate)GetValue(HeaderTemplateProperty); }
			set { SetValue(HeaderTemplateProperty, value); }
		}
		public object Icon {
			get { return GetValue(IconProperty); }
			set { SetValue(IconProperty, value); }
		}
		public bool IsRadioItem {
			get { return (bool)this.GetValue(IsRadioItemProperty); }
			set { base.SetValue(IsRadioItemProperty, value); }
		}
		public Orientation MenuOrientation {
			get { return (Orientation)GetValue(MenuOrientationProperty); }
			set { SetValue(MenuOrientationProperty, value); }
		}
		public AgMenuTemplateList TemplateCollection {
			get { return (AgMenuTemplateList)GetValue(TemplateCollectionProperty); }
			set { SetValue(TemplateCollectionProperty, value); }
		}
		public AgMenuItemViewStyle ViewStyle {
			get { return (AgMenuItemViewStyle)GetValue(ViewStyleProperty); }
			set { SetValue(ViewStyleProperty, value); }
		}
		public AgMenuItemPosition Position {
			get { return (AgMenuItemPosition)GetValue(PositionProperty); }
			set { SetValue(PositionProperty, value); }
		}
		public AgMenuItemContentPresenter() {
			Loaded += OnLoaded;
		}
		protected virtual void CheckAreaVisibilityChanged() {
			UpdateTemplateProperties();
		}
		protected virtual void ContentChanged(object oldValue) {
			UpdateTemplateProperties();
		}
		protected virtual void ContentTemplateChanged(DataTemplate oldValue) { }
		protected virtual void HeaderChanged(object oldValue) { }
		protected virtual void HeaderTemplateChanged(DataTemplate oldValue) { }
		protected virtual void IconChanged(object oldValue) {
			if (elementIconCheckAreaContainer != null)
				elementIconCheckAreaContainer.Width = Double.NaN;
			if (elementIconAreaContainer != null)
				elementIconAreaContainer.Width = Double.NaN;
			UpdateTemplateProperties();
		}
		protected virtual void IsRadioItemChanged() {
			UpdateTemplateProperties();
		}
		protected virtual void MenuOrientationChanged() { }
		protected virtual void TemplateCollectionChanged(AgMenuTemplateList oldValue) { }
		public override void OnApplyTemplate() {
			base.OnApplyTemplate();
			elementCheck = GetTemplateChild(ElementCheckName) as UIElement;
			elementCheckArea = GetTemplateChild(ElementCheckAreaName) as UIElement;
			elementCheckAreaContainer = GetTemplateChild(ElementCheckAreaContainerName) as FrameworkElement;
			elementIcon = GetTemplateChild(ElementIconName) as UIElement;
			elementIconArea = GetTemplateChild(ElementIconAreaName) as UIElement;
			elementIconAreaContainer = GetTemplateChild(ElementIconAreaContainerName) as FrameworkElement;
			elementIconCheckArea = GetTemplateChild(ElementIconCheckAreaName) as UIElement;
			elementIconCheckAreaContainer = GetTemplateChild(ElementIconCheckAreaContainerName) as FrameworkElement;
			elementRadio = GetTemplateChild(ElementRadioName) as UIElement;
			elementContent = GetTemplateChild(ElementContentName) as UIElement;
			elementRoot = GetTemplateChild(ElementRootName) as System.Windows.Controls.Panel;
			UpdateTemplateProperties();
		}
		protected virtual void ViewStyleChanged(AgMenuItemViewStyle oldValue) { }
		protected virtual void PositionChanged() { }
		UIElement GetIconCheckAreaElement(IconCheckAreaAreaKind areaKind, bool returnContainer) {
			UIElement result = null;
			switch (areaKind) {
				case IconCheckAreaAreaKind.Check:
					if (elementCheckAreaContainer != null && elementCheckAreaContainer.GetVisible() &&
						(elementIconAreaContainer == null || elementIconAreaContainer.GetVisible())) {
						result = returnContainer ? elementCheckAreaContainer : elementCheckArea;
					}
					break;
				case IconCheckAreaAreaKind.Icon:
					if (elementIconAreaContainer != null && !elementIconAreaContainer.GetVisible() &&
						elementCheckAreaContainer != null && elementCheckAreaContainer.GetVisible()) {
						result = returnContainer ? elementCheckAreaContainer : elementCheckArea;
					} else
						if (elementIconAreaContainer != null && elementIconAreaContainer.GetVisible())
							result = returnContainer ? elementIconAreaContainer : elementIconArea;
					break;
			}
			return result;
		}
		bool HasIconArea() {
			return this.elementIconAreaContainer != null && this.elementIconArea != null;
		}
		void OnLoaded(object sender, RoutedEventArgs e) {
			if (elementIconCheckAreaContainer != null)
				elementIconCheckAreaContainer.Width = Double.NaN;
			if (elementIconAreaContainer != null)
				elementIconAreaContainer.Width = Double.NaN;
		}
		void UpdateTemplateProperties() {
			if (elementRoot != null)
				foreach (UIElement child in elementRoot.Children)
					child.SetVisible(Content != null && (child == elementContent) || Content == null && (child != elementContent));
			if (Content == null) {
				if (elementIconAreaContainer != null)
					elementIconAreaContainer.SetVisible(CheckAreaVisibility != AgMenuItemCheckAreaVisibility.ReplaceIcon);
				if (elementCheckAreaContainer != null)
					elementCheckAreaContainer.SetVisible(CheckAreaVisibility != AgMenuItemCheckAreaVisibility.None);
				bool isCheckVisible = CheckAreaVisibility == AgMenuItemCheckAreaVisibility.ReplaceIcon || CheckAreaVisibility == AgMenuItemCheckAreaVisibility.ShowCheckInSeparateArea;
				if (elementCheck != null)
					elementCheck.SetVisible(isCheckVisible && !IsRadioItem);
				if (elementRadio != null)
					elementRadio.SetVisible(isCheckVisible && IsRadioItem);
			}
			if (Content != null) {
				if (elementCheck != null)
					elementCheck.SetVisible(CheckAreaVisibility != AgMenuItemCheckAreaVisibility.None && !IsRadioItem);
				if (elementRadio != null)
					elementRadio.SetVisible(CheckAreaVisibility != AgMenuItemCheckAreaVisibility.None && IsRadioItem);
			}
			if (elementIcon != null)
				elementIcon.SetVisible(Content == null && Icon != null);
		}
		#region Interfaces
		double IAgMenuItemContentPresenter.IconAreaLeft {
			get {
				return HasIconArea() ? this.elementIconAreaContainer.GetPositionNew(this).X : 0;
			}
		}
		double IAgMenuItemContentPresenter.IconAreaWidth {
			get {
				return HasIconArea() ? this.elementIconAreaContainer.DesiredSize.Width : 0;
			}
			set {
				if (HasIconArea())
					this.elementIconAreaContainer.Width = value;
			}
		}
		void IAgMenuItemContentPresenter.PrepareForVerticalLayout(List<IAgMenuItemContentPresenter> items) {
			foreach (IAgMenuItemContentPresenter item in items)
				if (!(item is AgMenuItemContentPresenter)) throw new Exception("item not is AgMenuItemContentPresenter");
			UIElement element;
			double maxCheckAreaWidth = 0, maxIconAreaWidth = 0, maxIconCheckAreaWidth = 0;
			foreach (AgMenuItemContentPresenter item in items) {
				element = item.GetIconCheckAreaElement(IconCheckAreaAreaKind.Check, false);
				if (element != null)
					maxCheckAreaWidth = Math.Max(maxCheckAreaWidth, element.DesiredSize.Width);
				element = item.GetIconCheckAreaElement(IconCheckAreaAreaKind.Icon, false);
				if (element != null)
					maxIconAreaWidth = Math.Max(maxIconAreaWidth, element.DesiredSize.Width);
			}
			maxCheckAreaWidth = Math.Ceiling(maxCheckAreaWidth);
			maxIconAreaWidth = Math.Ceiling(maxIconAreaWidth);
			foreach (AgMenuItemContentPresenter item in items) {
				element = item.GetIconCheckAreaElement(IconCheckAreaAreaKind.Check, true);
				if (element != null)
					((FrameworkElement)element).Width = maxCheckAreaWidth;
				element = item.GetIconCheckAreaElement(IconCheckAreaAreaKind.Icon, true);
				if (element != null)
					((FrameworkElement)element).Width = maxIconAreaWidth;
			}
			foreach (AgMenuItemContentPresenter item in items)
				item.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
			foreach (AgMenuItemContentPresenter item in items)
				if (item.elementIconCheckArea != null)
					maxIconCheckAreaWidth = Math.Max(maxIconCheckAreaWidth, item.elementIconCheckArea.DesiredSize.Width);
			maxIconCheckAreaWidth = Math.Ceiling(maxIconCheckAreaWidth);
			foreach (AgMenuItemContentPresenter item in items)
				if (item.elementIconCheckAreaContainer != null)
					item.elementIconCheckAreaContainer.Width = maxIconCheckAreaWidth;
		}
		#endregion
	}
}
